package com.dj.util;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.dj.pojo.AccessToken;
import com.dj.pojo.SNSUserInfo;
import com.dj.pojo.WeixinOauth2Token;
import com.dj.pojo.WeixinUrl;

@Component
public class WeiXinUtil{
	protected static Logger logger = LoggerFactory.getLogger(WeiXinUtil.class);
	
	// 从微信后台拿到APPID和APPSECRET 并封装为常量
	public static final String APPID = "wx90902aef5a1fe7e0";
	public static final String APPSECRET = "fffdefc09b539e44e5eb8a3f6ebd29b8";

	/**
	 * 测试
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		AccessToken token = WeiXinUtil.getAccessToken();
		System.out.println("token:" + token.getToken());
		System.out.println("有效时间:" + token.getExpiresIn());

		/*String path = "E:\\images\\girl.jpg";
		String mediaId = WeiXinUtil.upload(path, token.getToken(), "image");
		System.out.println(mediaId);*/
		
		String menu = JSONObject.toJSONString(InitUtil.initMenu());
		System.out.println(menu);
		int result = WeiXinUtil.createMenu(token.getToken(), menu);
		System.out.println(result);
		if(result==0){
			System.out.println("菜单创建成功！");
		} else {
			System.out.println("菜单创建失败！");
		}
	}

	/**
	 * 获取AccessToken
	 * 
	 * @return 返回拿到的access_token及有效期
	 */
	public static AccessToken getAccessToken() throws Exception {
		AccessToken token = new AccessToken();
		String url = WeixinUrl.ACCESS_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
		JSONObject jsonObject = RequestUtil.doGetRequest(url);
		if (jsonObject != null) { 
			token.setToken(jsonObject.getString("access_token"));
			token.setExpiresIn(jsonObject.getInteger("expires_in"));// 取出access_token的有效期
		}
		return token;
	}

	/**
	 * 上传文件到微信平台
	 * 
	 * @param filePath
	 *            文件地址
	 * @param accessToken
	 *            接口凭证
	 * @param type
	 *            类型
	 * @return
	 * @throws Exception
	 */
	public static String upload(String filePath, String accessToken, String type) throws Exception {
		File file = new File(filePath);
		// 判断文件是否存在
		if (!file.exists() || !file.isFile()) {
			throw new IOException("文件不存在!");
		}

		String url = WeixinUrl.UPLOAD_URL.replace("ACCESS_TOKEN", accessToken).replace("TYPE", type);
		URL urlObj = new URL(url);

		// 使用HttpURLConnection连接
		HttpURLConnection con = (HttpURLConnection) urlObj.openConnection();
		con.setRequestMethod("POST");
		con.setDoInput(true);
		con.setDoOutput(true);
		con.setUseCaches(true);// 忽略缓存

		// 设置请求头信息
		con.setRequestProperty("Connection", "Keep-Alive");
		con.setRequestProperty("Charset", "UTF-8");
		String BOUNDARY = "---------" + System.currentTimeMillis();
		con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);

		StringBuilder sb = new StringBuilder();
		sb.append("--");
		sb.append(BOUNDARY);
		sb.append("\r\n");
		sb.append("Content-Disposition:from-data;name=\"file\";filename=\"" + file.getName() + "\"\r\n");
		sb.append("Content-Type:application/octet-stream\r\n\r\n");

		byte[] head = sb.toString().getBytes();

		DataOutputStream out = new DataOutputStream(con.getOutputStream());
		out.write(head);

		// 文件正文部分
		DataInputStream in = new DataInputStream(new FileInputStream(file));
		int bytes = 0;
		byte[] bufferOut = new byte[1024];
		while ((bytes = in.read(bufferOut)) != -1) {
			out.write(bufferOut, 0, bytes);
		}
		in.close();

		// 结尾部分
		byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");
		out.write(foot);
		out.flush();
		out.close();

		StringBuffer buffer = new StringBuffer();
		BufferedReader reader = null;
		String result = null;

		try {
			// 定义BufferReader来读取url的响应
			reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
			String line = null;
			while ((line = reader.readLine()) != null) {
				buffer.append(line);
			}
			if (result == null) {
				result = buffer.toString();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (reader != null) {
				reader.close();
			}
		}

		JSONObject jsonObj = JSONObject.parseObject(result);
		System.out.println(jsonObj);
		String typeName = "media_id";
		if (!"image".equals(type)) {
			typeName = type + "_meida_id";
		}
		// 从json中取出mediaId
		String mediaId = jsonObj.getString(typeName);

		return mediaId;
	}

	

	/**
	 * 创建菜单
	 * 
	 * @param token
	 * @param menu
	 * @return
	 * @throws Exception
	 */
	public static int createMenu(String token, String menu) throws Exception {
		int result = 0;
		String url = WeixinUrl.CREATE_MENU_URL.replace("ACCESS_TOKEN", token);
		JSONObject jsonObject = RequestUtil.doPostRequest(url, menu);
		if (jsonObject != null) {
			result = jsonObject.getInteger("errcode");
		}
		return result;
	}
	
	/**
     * 获取网页授权凭证
     * 
     * @param appId 公众账号的唯一标识
     * @param appSecret 公众账号的密钥
     * @param code
     * @return WeixinAouth2Token
	 * @throws Exception 
     */
    public static WeixinOauth2Token getOauth2AccessToken(String appId, String appSecret, String code) throws Exception {
        WeixinOauth2Token wat = null;
        // 拼接请求地址
        String url = WeixinUrl.WEB_ACCESS_TOKEN_URL.replace("APPID", appId)
        		.replace("SECRET", appSecret).replace("CODE", code);
        // 获取网页授权凭证
        JSONObject jsonObject = RequestUtil.doGetRequest(url);
        if (null != jsonObject) {
            try {
                wat = new WeixinOauth2Token();
                wat.setAccessToken(jsonObject.getString("access_token"));
                wat.setExpiresIn(jsonObject.getInteger("expires_in"));
                wat.setRefreshToken(jsonObject.getString("refresh_token"));
                wat.setOpenId(jsonObject.getString("openid"));
                wat.setScope(jsonObject.getString("scope"));
            } catch (Exception e) {
                wat = null;
                int errorCode = jsonObject.getInteger("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                logger.error("获取网页授权凭证失败 errcode:{} errmsg:{}", errorCode, errorMsg);
            }
        }
        return wat;
    }
    
    /**
     * 通过网页授权获取用户信息
     * 
     * @param accessToken 网页授权接口调用凭证
     * @param openId 用户标识
     * @return SNSUserInfo
     * @throws Exception 
     */
    public static SNSUserInfo getSNSUserInfo(String accessToken, String openId) throws Exception {
        SNSUserInfo snsUserInfo = null;
        // 拼接请求地址
        String url = WeixinUrl.USER_INFO_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
        
        // 通过网页授权获取用户信息
        JSONObject jsonObject = RequestUtil.doGetRequest(url);

        if (null != jsonObject) {
            try {
                snsUserInfo = new SNSUserInfo();
                // 用户的标识
                snsUserInfo.setOpenId(jsonObject.getString("openid"));
                // 昵称
                snsUserInfo.setNickname(jsonObject.getString("nickname"));
                // 性别（1是男性，2是女性，0是未知）
                snsUserInfo.setSex(jsonObject.getInteger("sex"));
                // 用户所在国家
                snsUserInfo.setCountry(jsonObject.getString("country"));
                // 用户所在省份
                snsUserInfo.setProvince(jsonObject.getString("province"));
                // 用户所在城市
                snsUserInfo.setCity(jsonObject.getString("city"));
                // 用户头像
                snsUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
                // 用户特权信息
                snsUserInfo.setPrivilegeList(JSONObject.parseArray(jsonObject.getJSONArray("privilege").toJSONString(), String.class));
            } catch (Exception e) {
                snsUserInfo = null;
                int errorCode = jsonObject.getInteger("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                logger.error("获取用户信息失败 errcode:{} errmsg:{}", errorCode, errorMsg);
            }
        }
        return snsUserInfo;
    }
}
